package com.flynn.rock.crm.service.employee.impl;

import com.flynn.rock.crm.convert.AbstractEmployeeConvert;
import com.flynn.rock.crm.entity.employee.EmployeeEntity;
import com.flynn.rock.crm.model.employee.EmployeeCriteria;
import com.flynn.rock.crm.model.employee.request.PageEmployeeRequest;
import com.flynn.rock.crm.model.employee.request.ReceiveOrdersRequest;
import com.flynn.rock.crm.model.employee.request.SaveEmployeeRequest;
import com.flynn.rock.crm.model.employee.vo.EmployeeIdVo;
import com.flynn.rock.crm.model.employee.vo.EmployeeVo;
import com.flynn.rock.crm.model.employee.vo.ReceiveOrdersConfigVo;
import com.flynn.rock.crm.repository.customer.CustomerRepository;
import com.flynn.rock.crm.repository.employee.EmployeeRepository;
import com.flynn.rock.crm.service.employee.EmployeeService;
import com.flynn.rock.enums.customer.ReceiveStatus;
import com.flynn.rock.model.PageResult;
import com.flynn.rock.system.api.ISysUserApi;
import com.flynn.rock.system.model.dto.SaveUserDto;
import com.flynn.rock.system.model.vo.UserIdVo;
import com.flynn.rock.util.PageUtil;
import com.flynn.rock.util.SecurityUtil;
import jakarta.annotation.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Resource
    private EmployeeRepository employeeRepository;

    @Resource
    private CustomerRepository customerRepository;

    @Resource
    private ISysUserApi sysUserApi;

    @Transactional
    @Override
    public EmployeeIdVo saveEmployee(SaveEmployeeRequest request) {
        EmployeeEntity employeeEntity = AbstractEmployeeConvert.INSTANCE.toEmployeeEntity(request);
        employeeEntity.setReceiveNumber(0);
        employeeEntity.setReceivePriority(0);
        employeeEntity.setReceiveStatus(ReceiveStatus.DISABLE);
        employeeEntity.setCreateUserId(SecurityUtil.getCurrentUserId());
        SaveUserDto userDto = AbstractEmployeeConvert.INSTANCE.toUserDto(request);
        if (Objects.nonNull(request.getEmployeeId())) {
            EmployeeEntity oldEmployeeEntity = employeeRepository.findById(request.getEmployeeId()).orElseThrow();
            this.fillNewEmployeeEntity(employeeEntity, oldEmployeeEntity);
            userDto.setUserId(oldEmployeeEntity.getUserId());
            userDto.setUserCode(oldEmployeeEntity.getUserCode());
        }
        userDto.setCreateUserId(employeeEntity.getCreateUserId());
        UserIdVo userIdVo = sysUserApi.saveUser(userDto);
        employeeEntity.setUserId(userIdVo.getUserId());
        employeeEntity.setUserCode(userIdVo.getUserCode());
        employeeEntity = employeeRepository.save(employeeEntity);
        return EmployeeIdVo.builder()
                .employeeId(employeeEntity.getEmployeeId())
                .userId(employeeEntity.getUserId())
                .userCode(userIdVo.getUserCode())
                .build();
    }

    private void fillNewEmployeeEntity(EmployeeEntity newEmployeeEntity, EmployeeEntity oldEmployeeEntity) {
        newEmployeeEntity.setEmployeeId(oldEmployeeEntity.getEmployeeId());
        newEmployeeEntity.setUserId(oldEmployeeEntity.getUserId());
        newEmployeeEntity.setUserCode(oldEmployeeEntity.getUserCode());
        newEmployeeEntity.setReceiveNumber(oldEmployeeEntity.getReceiveNumber());
        newEmployeeEntity.setReceivePriority(oldEmployeeEntity.getReceivePriority());
        newEmployeeEntity.setReceiveStatus(oldEmployeeEntity.getReceiveStatus());
        newEmployeeEntity.setFollowUpNumber(oldEmployeeEntity.getFollowUpNumber());
        newEmployeeEntity.setStatus(oldEmployeeEntity.getStatus());
        newEmployeeEntity.setCreateTime(oldEmployeeEntity.getCreateTime());
    }

    @Override
    public EmployeeVo getEmployee(Long employeeId) {
        EmployeeEntity employee = employeeRepository.findById(employeeId).orElseThrow();
        return AbstractEmployeeConvert.INSTANCE.toEmployeeVo(employee);
    }

    @Override
    public void deleteEmployee(Long employeeId) {
        EmployeeEntity employeeEntity = employeeRepository.findById(employeeId).orElseThrow();
        customerRepository.updateFollowUpUserNull(employeeEntity.getUserId());
        sysUserApi.deleteUser(employeeEntity.getUserId());
        employeeRepository.delete(employeeEntity);
    }

    @Override
    public PageResult<EmployeeVo> pageEmployee(PageEmployeeRequest request) {
        PageRequest pageRequest = PageRequest.of(request.getPageNum() - 1, request.getPageSize());
        pageRequest = pageRequest.withSort(Sort.sort(EmployeeEntity.class).by(EmployeeEntity::getUpdateTime).descending());
        EmployeeCriteria employeeCriteria = EmployeeCriteria.builder()
                .realName(request.getRealName())
                .phone(request.getPhone())
                .build();
        Page<EmployeeEntity> entities = employeeRepository.pageEmployee(employeeCriteria, pageRequest);
        return PageUtil.toPage(entities.map(AbstractEmployeeConvert.INSTANCE::toEmployeeVo));
    }

    @Override
    public EmployeeIdVo receiveOrdersConfig(ReceiveOrdersRequest request) {
        EmployeeEntity employeeEntity = employeeRepository.findById(request.getEmployeeId()).orElseThrow();
        employeeEntity.setReceiveStatus(request.getReceiveStatus());
        employeeEntity.setReceiveNumber(request.getReceiveNumber());
        employeeEntity.setReceivePriority(request.getReceivePriority());
        employeeEntity = employeeRepository.save(employeeEntity);
        return EmployeeIdVo.builder()
                .employeeId(employeeEntity.getEmployeeId())
                .userId(employeeEntity.getUserId())
                .userCode(employeeEntity.getUserCode())
                .build();
    }

    @Override
    public PageResult<ReceiveOrdersConfigVo> pageReceiveOrdersConfig(PageEmployeeRequest request) {
        EmployeeCriteria employeeCriteria = EmployeeCriteria.builder()
                .realName(request.getRealName())
                .phone(request.getPhone())
                .build();
        PageRequest pageRequest = PageRequest.of(request.getPageNum() - 1, request.getPageSize());
        pageRequest = pageRequest.withSort(Sort.sort(EmployeeEntity.class).by(EmployeeEntity::getUpdateTime).descending());
        Page<EmployeeEntity> entities = employeeRepository.pageEmployee(employeeCriteria, pageRequest);
        return PageUtil.toPage(entities.map(AbstractEmployeeConvert.INSTANCE::toReceiveOrdersConfigVo));
    }

    @Override
    public ReceiveOrdersConfigVo getReceiveOrdersConfig(Long employeeId) {
        EmployeeEntity employeeEntity = employeeRepository.findById(employeeId).orElseThrow();
        return AbstractEmployeeConvert.INSTANCE.toReceiveOrdersConfigVo(employeeEntity);
    }
}
